/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package cz.muni.fi.pv168.reminder.swing;

import cz.muni.fi.pv168.reminder.entities.Task;
import cz.muni.fi.pv168.reminder.entities.Worker;
import cz.muni.fi.pv168.reminder.managers.TaskManager;
import cz.muni.fi.pv168.reminder.swing.workers.AddTaskSwingWorker;
import cz.muni.fi.pv168.reminder.swing.workers.AssignWorkersSwingWorker;
import cz.muni.fi.pv168.reminder.swing.workers.GetTaskSwingWorker;
import cz.muni.fi.pv168.reminder.swing.workers.LoadTasksSwingWorker;
import cz.muni.fi.pv168.reminder.swing.workers.UpdateTaskSwingWorker;
import java.awt.Color;
import java.awt.Component;
import java.awt.Font;
import java.io.IOException;
import java.io.InputStream;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.Properties;
import java.util.concurrent.ExecutionException;
import java.util.logging.FileHandler;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.logging.SimpleFormatter;
import javax.swing.JTable;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableRowSorter;
import org.apache.commons.dbcp.BasicDataSource;

/**
 *
 * @author Adic
 */
public class FrameMainWindow extends javax.swing.JFrame {
    private static final Logger logger = Logger.getLogger("Reminder");
    
    private static BasicDataSource dataSource = null;

    /**
     * Creates new form FrameMainWindow
     */
    public FrameMainWindow() {
        initComponents();
        ((TableTaskModel) jTable2.getModel())
                .setFilter(jCheckBoxDisplayAll1.isSelected(), jCheckBoxDisplayDone.isSelected(), jCheckBoxDisplayPending.isSelected(), jCheckBoxOver.isSelected());      
    }
    /*
    /**
     * @deprecated
    public JTable getTable() {
        return jTable2;
    }*/

    /**
     * Return data source for DB connection. 
     * Singleton.
     * 
     * @return 
     */
    public static BasicDataSource getDataSource() {
        if (dataSource == null) {
            dataSource = new BasicDataSource();
            Properties prop = new Properties();
            InputStream is = TaskManager.class.getResourceAsStream("jdbc.properties"); //NOI18N

            try {
                prop.load(is);
                is.close();
            } catch (IOException e) {
                logger.log(Level.SEVERE, "Can't load dataSource.", e);
                return null;
            }

            dataSource.setUsername(prop.getProperty("user")); //NOI18N 
            dataSource.setPassword(prop.getProperty("pass")); //NOI18N
            dataSource.setUrl(prop.getProperty("url")); //NOI18N
        }

        return dataSource;
    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        jPanel7 = new javax.swing.JPanel();
        jButtonAddTask1 = new javax.swing.JButton();
        jButtonShowDetail1 = new javax.swing.JButton();
        jScrollPane5 = new javax.swing.JScrollPane();
        jTable2 = new javax.swing.JTable();
        jPanel8 = new javax.swing.JPanel();
        jCheckBoxDisplayAll1 = new javax.swing.JCheckBox();
        jCheckBoxDisplayDone = new javax.swing.JCheckBox();
        jCheckBoxDisplayPending = new javax.swing.JCheckBox();
        jCheckBoxOver = new javax.swing.JCheckBox();
        jLabel10 = new javax.swing.JLabel();
        jMenuBar1 = new javax.swing.JMenuBar();
        jMenu1 = new javax.swing.JMenu();
        jMenuItem9 = new javax.swing.JMenuItem();
        jSeparator3 = new javax.swing.JPopupMenu.Separator();
        jMenuItem2 = new javax.swing.JMenuItem();
        jMenu2 = new javax.swing.JMenu();
        jMenuItem4 = new javax.swing.JMenuItem();
        jMenu4 = new javax.swing.JMenu();
        jMenuItem7 = new javax.swing.JMenuItem();
        jSeparator2 = new javax.swing.JPopupMenu.Separator();
        jMenuItem8 = new javax.swing.JMenuItem();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        java.util.ResourceBundle bundle = java.util.ResourceBundle.getBundle("cz/muni/fi/pv168/reminder/swing/Strings"); // NOI18N
        jButtonAddTask1.setText(bundle.getString("ADD TASK")); // NOI18N
        jButtonAddTask1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButtonAddTask1ActionPerformed(evt);
            }
        });

        jButtonShowDetail1.setText(bundle.getString("EDIT")); // NOI18N
        jButtonShowDetail1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButtonShowDetail1ActionPerformed(evt);
            }
        });

        jTable2.setModel(new TableTaskModel());
        jTable2.setDefaultRenderer(Object.class, new ColorCellRenderer());
        jTable2.setDefaultRenderer (Date.class, new DateCellRenderer());
        jTable2.setDefaultRenderer (Boolean.class, new BooleanCellRenderer());
        jScrollPane5.setViewportView(jTable2);

        jPanel8.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(0, 0, 0)));

        jCheckBoxDisplayAll1.setText(bundle.getString("ALL")); // NOI18N
        jCheckBoxDisplayAll1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jCheckBoxDisplayAll1ActionPerformed(evt);
            }
        });

        jCheckBoxDisplayDone.setText(bundle.getString("DONE")); // NOI18N
        jCheckBoxDisplayDone.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jCheckBoxDisplayDoneActionPerformed(evt);
            }
        });

        jCheckBoxDisplayPending.setText(bundle.getString("PENDING")); // NOI18N
        jCheckBoxDisplayPending.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jCheckBoxDisplayPendingActionPerformed(evt);
            }
        });

        jCheckBoxOver.setSelected(true);
        jCheckBoxOver.setText(bundle.getString("OVER DEADLINE")); // NOI18N
        jCheckBoxOver.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jCheckBoxOverActionPerformed(evt);
            }
        });

        jLabel10.setText(bundle.getString("DISPLAY:")); // NOI18N

        javax.swing.GroupLayout jPanel8Layout = new javax.swing.GroupLayout(jPanel8);
        jPanel8.setLayout(jPanel8Layout);
        jPanel8Layout.setHorizontalGroup(
            jPanel8Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel8Layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jLabel10)
                .addGap(40, 40, 40)
                .addComponent(jCheckBoxDisplayAll1)
                .addGap(18, 18, 18)
                .addComponent(jCheckBoxDisplayDone)
                .addGap(18, 18, 18)
                .addComponent(jCheckBoxDisplayPending)
                .addGap(18, 18, 18)
                .addComponent(jCheckBoxOver)
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );
        jPanel8Layout.setVerticalGroup(
            jPanel8Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel8Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                .addComponent(jCheckBoxDisplayDone)
                .addComponent(jCheckBoxOver)
                .addComponent(jCheckBoxDisplayPending)
                .addComponent(jCheckBoxDisplayAll1)
                .addComponent(jLabel10))
        );

        javax.swing.GroupLayout jPanel7Layout = new javax.swing.GroupLayout(jPanel7);
        jPanel7.setLayout(jPanel7Layout);
        jPanel7Layout.setHorizontalGroup(
            jPanel7Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel7Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel7Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jScrollPane5)
                    .addGroup(jPanel7Layout.createSequentialGroup()
                        .addComponent(jButtonAddTask1)
                        .addGap(18, 18, 18)
                        .addComponent(jPanel8, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addGap(18, 18, 18)
                        .addComponent(jButtonShowDetail1, javax.swing.GroupLayout.DEFAULT_SIZE, 85, Short.MAX_VALUE))))
        );
        jPanel7Layout.setVerticalGroup(
            jPanel7Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel7Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel7Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jPanel8, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(jButtonShowDetail1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(jButtonAddTask1, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                .addGap(35, 35, 35)
                .addComponent(jScrollPane5, javax.swing.GroupLayout.DEFAULT_SIZE, 482, Short.MAX_VALUE)
                .addContainerGap())
        );

        jMenu1.setText(bundle.getString("FILE")); // NOI18N

        jMenuItem9.setText(bundle.getString("RELOAD")); // NOI18N
        jMenuItem9.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jMenuItem9ActionPerformed(evt);
            }
        });
        jMenu1.add(jMenuItem9);
        jMenu1.add(jSeparator3);

        jMenuItem2.setText(bundle.getString("END")); // NOI18N
        jMenuItem2.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jMenuItem2ActionPerformed(evt);
            }
        });
        jMenu1.add(jMenuItem2);

        jMenuBar1.add(jMenu1);

        jMenu2.setText(bundle.getString("TASKS")); // NOI18N

        jMenuItem4.setText(bundle.getString("ADD TASK")); // NOI18N
        jMenuItem4.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jMenuItem4ActionPerformed(evt);
            }
        });
        jMenu2.add(jMenuItem4);

        jMenuBar1.add(jMenu2);

        jMenu4.setText(bundle.getString("WORKERS")); // NOI18N

        jMenuItem7.setText(bundle.getString("ADD WORKER")); // NOI18N
        jMenuItem7.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jMenuItem7ActionPerformed(evt);
            }
        });
        jMenu4.add(jMenuItem7);
        jMenu4.add(jSeparator2);

        jMenuItem8.setText(bundle.getString("SHOW ALL WORKERS")); // NOI18N
        jMenuItem8.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jMenuItem8ActionPerformed(evt);
            }
        });
        jMenu4.add(jMenuItem8);

        jMenuBar1.add(jMenu4);

        setJMenuBar(jMenuBar1);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addComponent(jPanel7, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jPanel7, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void jButtonAddTask1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButtonAddTask1ActionPerformed
        createTask();
        //todo
    }//GEN-LAST:event_jButtonAddTask1ActionPerformed

    /**
     * Shows AddTask dialog and process result.
     */
    private void createTask() {
        DialogAddTask addTaskDialog = new DialogAddTask(this, true);
        addTaskDialog.pack();
        addTaskDialog.setVisible(Boolean.TRUE);
        Task task = addTaskDialog.getTask();
        if (task != null) {
            ((TableTaskModel) jTable2.getModel()).addTask(task);
        }
    }

    private void jButtonShowDetail1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButtonShowDetail1ActionPerformed
        if (jTable2.getSelectedRow() == -1) {
            return;
        }
        Task task = ((TableTaskModel) jTable2.getModel()).getTaskAtRow(jTable2.convertRowIndexToModel(jTable2.getSelectedRow()));
        if (task == null) {
            return;
        }
        DialogTaskDetail taskDetailDialog = new DialogTaskDetail(this, true, task.getId());

        taskDetailDialog.pack();
        taskDetailDialog.setVisible(Boolean.TRUE);

        Task returnedTask = taskDetailDialog.getTask();
        List<Worker> workers = taskDetailDialog.getWorkers();

        ((TableTaskModel) jTable2.getModel()).update(returnedTask);
        AssignWorkersSwingWorker assignWorkersSwingWorker = new AssignWorkersSwingWorker(returnedTask, workers);
        assignWorkersSwingWorker.execute();
        try {
            assignWorkersSwingWorker.get();
            logger.info("Workers working on task: " + returnedTask + " updated. Current number of workers: " + workers.size());
        } catch (InterruptedException | ExecutionException ex) {
            logger.log(Level.SEVERE, "Can't assign workers to task.", ex);
        }


    }//GEN-LAST:event_jButtonShowDetail1ActionPerformed

    private void jMenuItem2ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jMenuItem2ActionPerformed

    }//GEN-LAST:event_jMenuItem2ActionPerformed

    private void jMenuItem4ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jMenuItem4ActionPerformed
        createTask();
    }//GEN-LAST:event_jMenuItem4ActionPerformed

    private void jMenuItem8ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jMenuItem8ActionPerformed
        DialogMainWorker mainWorkers = new DialogMainWorker(this, true);
        mainWorkers.pack();
        mainWorkers.setVisible(Boolean.TRUE);
    }//GEN-LAST:event_jMenuItem8ActionPerformed

    private void jMenuItem9ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jMenuItem9ActionPerformed
        ((TableTaskModel) jTable2.getModel()).reload();
    }//GEN-LAST:event_jMenuItem9ActionPerformed

    private void jCheckBoxDisplayAll1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jCheckBoxDisplayAll1ActionPerformed
        jCheckBoxDisplayAll1.setSelected(jCheckBoxDisplayAll1.isSelected());
        jCheckBoxDisplayDone.setSelected(Boolean.FALSE);
        jCheckBoxDisplayPending.setSelected(Boolean.FALSE);
        jCheckBoxOver.setSelected(Boolean.FALSE);
        ((TableTaskModel) jTable2.getModel())
                .setFilter(jCheckBoxDisplayAll1.isSelected(), jCheckBoxDisplayDone.isSelected(), jCheckBoxDisplayPending.isSelected(), jCheckBoxOver.isSelected());

    }//GEN-LAST:event_jCheckBoxDisplayAll1ActionPerformed

    private void jCheckBoxDisplayDoneActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jCheckBoxDisplayDoneActionPerformed
        jCheckBoxDisplayAll1.setSelected(Boolean.FALSE);
        jCheckBoxDisplayDone.setSelected(jCheckBoxDisplayDone.isSelected());
        ((TableTaskModel) jTable2.getModel())
                .setFilter(jCheckBoxDisplayAll1.isSelected(), jCheckBoxDisplayDone.isSelected(), jCheckBoxDisplayPending.isSelected(), jCheckBoxOver.isSelected());
    }//GEN-LAST:event_jCheckBoxDisplayDoneActionPerformed

    private void jCheckBoxDisplayPendingActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jCheckBoxDisplayPendingActionPerformed
        jCheckBoxDisplayAll1.setSelected(Boolean.FALSE);
        jCheckBoxDisplayPending.setSelected(jCheckBoxDisplayPending.isSelected());
        ((TableTaskModel) jTable2.getModel())
                .setFilter(jCheckBoxDisplayAll1.isSelected(), jCheckBoxDisplayDone.isSelected(), jCheckBoxDisplayPending.isSelected(), jCheckBoxOver.isSelected());
    }//GEN-LAST:event_jCheckBoxDisplayPendingActionPerformed

    private void jCheckBoxOverActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jCheckBoxOverActionPerformed
        jCheckBoxDisplayAll1.setSelected(Boolean.FALSE);
        jCheckBoxOver.setSelected(jCheckBoxOver.isSelected());
        ((TableTaskModel) jTable2.getModel())
                .setFilter(jCheckBoxDisplayAll1.isSelected(), jCheckBoxDisplayDone.isSelected(), jCheckBoxDisplayPending.isSelected(), jCheckBoxOver.isSelected());
    }//GEN-LAST:event_jCheckBoxOverActionPerformed

    private void jMenuItem7ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jMenuItem7ActionPerformed
        DialogAddWorker addWorker = new DialogAddWorker(this, Boolean.TRUE);
        addWorker.pack();
        addWorker.setVisible(Boolean.TRUE);
        
        Worker worker = addWorker.getWorker();
        if(worker != null){
            AddWorkerSwingWorker addWorkerSwingWorker = new AddWorkerSwingWorker(worker);
            addWorkerSwingWorker.execute();
            try {
                addWorkerSwingWorker.get();
                logger.info("Worker " + worker + " created.");
            } catch (InterruptedException | ExecutionException ex) {
                logger.log(Level.SEVERE, "Failed to create worker " + worker, ex);
            }
        }
    }//GEN-LAST:event_jMenuItem7ActionPerformed

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        /* Set the Nimbus look and feel */
        //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
        /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
         * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html 
         */
        FileHandler fileHandler;
        try {
            fileHandler = new FileHandler("Reminder.log");
            logger.addHandler(fileHandler);
            SimpleFormatter formatter = new SimpleFormatter();  
            fileHandler.setFormatter(formatter);  
            logger.setUseParentHandlers(false);
        } catch (IOException | SecurityException ex) {
            logger.log(Level.SEVERE, "Can't load log file.", ex);
        }                
        
        try {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) { //NOI18N
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | javax.swing.UnsupportedLookAndFeelException ex) {
            logger.log(java.util.logging.Level.SEVERE, null, ex);
        }
        //</editor-fold>

        /* Create and display the form */
        java.awt.EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                new FrameMainWindow().setVisible(true);
            }
        });
    }

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton jButtonAddTask1;
    private javax.swing.JButton jButtonShowDetail1;
    private javax.swing.JCheckBox jCheckBoxDisplayAll1;
    private javax.swing.JCheckBox jCheckBoxDisplayDone;
    private javax.swing.JCheckBox jCheckBoxDisplayPending;
    private javax.swing.JCheckBox jCheckBoxOver;
    private javax.swing.JLabel jLabel10;
    private javax.swing.JMenu jMenu1;
    private javax.swing.JMenu jMenu2;
    private javax.swing.JMenu jMenu4;
    private javax.swing.JMenuBar jMenuBar1;
    private javax.swing.JMenuItem jMenuItem2;
    private javax.swing.JMenuItem jMenuItem4;
    private javax.swing.JMenuItem jMenuItem7;
    private javax.swing.JMenuItem jMenuItem8;
    private javax.swing.JMenuItem jMenuItem9;
    private javax.swing.JPanel jPanel7;
    private javax.swing.JPanel jPanel8;
    private javax.swing.JScrollPane jScrollPane5;
    private javax.swing.JPopupMenu.Separator jSeparator2;
    private javax.swing.JPopupMenu.Separator jSeparator3;
    private javax.swing.JTable jTable2;
    // End of variables declaration//GEN-END:variables

    public static class TableTaskModel extends AbstractTableModel {

        private List<Task> tasks = new ArrayList<>();
        private LoadTasksSwingWorker loadTasksSwingWorker;
        private UpdateTaskSwingWorker updateTaskSwingWorker;
        private GetTaskSwingWorker getTaskSwingWorker;
        private AddTaskSwingWorker addTaskSwingWorker;
        private Boolean all, done, pending, over;

        public TableTaskModel() {
            all = Boolean.TRUE;
            done = Boolean.FALSE;
            pending = Boolean.FALSE;
            over = Boolean.FALSE;
            loadTasks();
            fireTableDataChanged();
        }

        /**
         * Set filter for loading tasks
         *
         * @param all
         * @param done
         * @param pending
         * @param over
         */
        public void setFilter(Boolean all, Boolean done, Boolean pending, Boolean over) {
            this.all = all;
            this.done = done;
            this.pending = pending;
            this.over = over;
            reload();
        }

        /**
         * Reloads tasks from DB
         */
        public void reload() {
            loadTasks();
            fireTableDataChanged();
        }

        /**
         * Loads tasks from DB with filters
         */
        private void loadTasks() {
            loadTasksSwingWorker = new LoadTasksSwingWorker(all, done, pending, over);
            loadTasksSwingWorker.execute();
            try {
                tasks = loadTasksSwingWorker.get();
                logger.info("Tasks loaded successfully");
            } catch (InterruptedException | ExecutionException ex) {
                logger.log(Level.SEVERE, "Can't load tasks.", ex);
                DBError error = new DBError(null, true);
                error.pack();
                error.setVisible(true);
            }
            if (tasks == null) {
                tasks = new ArrayList<>();
            }
        }

        /**
         * Add task to db
         *
         * @param task
         */
        public void addTask(Task task) {
            addTaskSwingWorker = new AddTaskSwingWorker(task, this);
            addTaskSwingWorker.execute();
            try {
                addTaskSwingWorker.get();
                logger.info("Task " + task + " created");
            } catch (InterruptedException | ExecutionException ex) {
                logger.log(Level.SEVERE, "Failed to create task " + task, ex);
            }

        }

        public Task getTaskAtRow(int row) {
            if (row < 0 || row > tasks.size() - 1) {
                return null;
            }
            return tasks.get(row);
        }

        @Override
        public int getRowCount() {
            return tasks.size();
        }

        @Override
        public int getColumnCount() {
            return 4;
        }

        @Override
        public Object getValueAt(int rowIndex, int columnIndex) {

            Task task = tasks.get(rowIndex);
            switch (columnIndex) {
                case 0:
                    return task.getName();
                case 1:
                    return task.getDeadline();
                case 2:
                    return task.getDone();
                case 3:
                    return task.getDescription();
                default:
                    throw new IllegalArgumentException("column Index"); //NOI18N

            }
        }

        @Override
        public Class<?> getColumnClass(int columnIndex) {
            switch (columnIndex) {
                case 0:
                case 3:
                    return String.class;
                case 1:
                    return Date.class;
                case 2:
                    return Boolean.class;
                default:
                    throw new IllegalArgumentException("columnIndex");  //NOI18N
            } 
        }

        @Override
        public String getColumnName(int column) {
            switch (column) {
                case 0:
                    return java.util.ResourceBundle.getBundle("cz/muni/fi/pv168/reminder/swing/Strings").getString("TASK");
                case 1:
                    return java.util.ResourceBundle.getBundle("cz/muni/fi/pv168/reminder/swing/Strings").getString("DEADLINE");
                case 2:
                    return java.util.ResourceBundle.getBundle("cz/muni/fi/pv168/reminder/swing/Strings").getString("STATE");
                case 3:
                    return java.util.ResourceBundle.getBundle("cz/muni/fi/pv168/reminder/swing/Strings").getString("DESCRIPTION");
                default:
                    throw new IllegalArgumentException("column Index"); //NOI18N

            }
        }

        /**
         * Return task from DB
         *
         * @param taskID
         * @return
         */
        Task getTask(Long taskID) {
            Task task = null;

            getTaskSwingWorker = new GetTaskSwingWorker(taskID);
            getTaskSwingWorker.execute();
            try {
                task = getTaskSwingWorker.get();
                logger.info("Task " + task + "retrieved");
            } catch (InterruptedException | ExecutionException ex) {
                logger.log(Level.SEVERE, "Failed to obtail task with id: " + taskID, ex);
                DBError error = new DBError(null, true);
                error.pack();
                error.setVisible(true);
            }
            return task;
        }

        /**
         * Update task
         *
         * @param returnedTask
         */
        private void update(Task returnedTask) {
            updateTaskSwingWorker = new UpdateTaskSwingWorker(returnedTask, this);
            updateTaskSwingWorker.execute();
            try {
                updateTaskSwingWorker.get();
                logger.info("Task "+returnedTask+" updated");
            } catch (InterruptedException | ExecutionException ex) {
                logger.log(Level.SEVERE, "Failed to update task " + returnedTask, ex);
            }
            reload();
        }

    }

    private static class ColorCellRenderer extends DefaultTableCellRenderer {

        @Override
        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
            super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
            int modelRow = table.convertRowIndexToModel(row);
            Task task = ((TableTaskModel) table.getModel()).getTaskAtRow(modelRow);
            if (task == null) {
                throw new IllegalArgumentException("rowIndex"); //NOI18N
            }
            Date now = new Date();
            if (task.getDeadline().before(now)&&!task.getDone()) {
                setBackground(Color.red);

            } else {
                setBackground(table.getBackground());
                setForeground(Color.black);
            }
            if(column == 3){
                String description = (String)value;
                if(description.length()>15)
                    description = description.substring(0, 15).concat("...");
                setText(description);
            }
            return this;
        }
    }

    private static class DateCellRenderer extends DefaultTableCellRenderer {

        @Override
        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
            super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
            DateFormat df = DateFormat.getDateInstance(DateFormat.LONG, Locale.getDefault());
            Date date = (Date) value;

            int modelRow = table.convertRowIndexToModel(row);
            Task task = ((TableTaskModel) table.getModel()).getTaskAtRow(modelRow);
            if (task == null) {
                throw new IllegalArgumentException("rowIndex"); //NOI18N
            }
            Date now = new Date();
            if (task.getDeadline().before(now)&&!task.getDone()) {
                setBackground(Color.red);
            } else {
                setBackground(table.getBackground());
                setForeground(Color.black);
            }
            setText(df.format(date));
            

            return this;
        }
    }

    private static class BooleanCellRenderer extends DefaultTableCellRenderer {

        @Override
        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
            super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); 
            //TODO format date - locale
            int modelRow = table.convertRowIndexToModel(row);
            Task task = ((TableTaskModel) table.getModel()).getTaskAtRow(modelRow);
            if (task == null) {
                throw new IllegalArgumentException("rowIndex"); //NOI18N
            }
            Date now = new Date();
            if (task.getDeadline().before(now)&&!task.getDone()) {
                setBackground(Color.red);
            } else {
                setBackground(table.getBackground());
                setForeground(Color.black);
            }
            
            Boolean state = (Boolean) value;
            if(state.booleanValue()){
                setText("Done");
            }else{
                setText("Not Done");
            }

            return this;
        }

      
    }

}
